package com.baomidou.springwind.pojo;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.springwind.baidu.Geocoder;
import com.baomidou.springwind.entity.NetworkDelivery;
import com.baomidou.springwind.mapper.NetworkDeliveryDao;
import com.baomidou.springwind.utils.CityUtil;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.*;


public class Test2 {
    @Autowired
    private NetworkDeliveryDao networkDeliveryDao;
    public void siteSelection(){
        List<NetworkDelivery> networkDeliveries=getNetworkDelivey();
        List<NetworkDelivery> firstDeliveryList = new ArrayList<NetworkDelivery>();
        List<NetworkDelivery> secondDeliveryList = new ArrayList<NetworkDelivery>();
        for (int i=0;i<networkDeliveries.size();i++){
            if (networkDeliveries.get(i).getType()==1){
                firstDeliveryList.add(networkDeliveries.get(i));
            }
            if (networkDeliveries.get(i).getType()==2){
                secondDeliveryList.add(networkDeliveries.get(i));
            }
        }
        BigDecimal bigDecimalavg=getStep1(firstDeliveryList);
        double coefficient1=0.5;
        double coefficient2=2;
        BigDecimal q1 = bigDecimalavg.multiply(new BigDecimal(coefficient1));
        BigDecimal q2 = bigDecimalavg.multiply(new BigDecimal(coefficient2));
        List<NetworkDelivery> s1 = new ArrayList<NetworkDelivery>();
        List<NetworkDelivery> s2 = new ArrayList<NetworkDelivery>();
        Set<Long> ids = new HashSet<Long>();
        Set<NetworkDelivery> exsits = new HashSet<NetworkDelivery>();
        for (int i=0;i<firstDeliveryList.size();i++){
            if(firstDeliveryList.get(i).getOrderQuantity().compareTo(q1)<0){
                s1.add(firstDeliveryList.get(i));
            } else if (firstDeliveryList.get(i).getOrderQuantity().compareTo(q2)>0){

            }else{
                s2.add(firstDeliveryList.get(i));
            }
        }
        List<SiteDistance> siteDistanceSet = new ArrayList<SiteDistance>();
        for (int i=0;i<s1.size();i++){
            for (int j=i+1;j<s1.size();j++){
                siteDistanceSet.add(new SiteDistance(s1.get(i),s1.get(j)));
            }
            for (int j1=0;j1<s2.size();j1++){
                siteDistanceSet.add(new SiteDistance(s1.get(i),s2.get(j1)));
            }
            ids.add(s1.get(i).getId());
        }
        Collections.sort(siteDistanceSet, new Comparator<SiteDistance>() {
            @Override
            public int compare(SiteDistance o1, SiteDistance o2) {
                return o1.disance.compareTo(o2.disance);
            }
        });
        List<SiteDistance> selectedList = new ArrayList<SiteDistance>();
        for (SiteDistance sd: siteDistanceSet){
            if(ids.size()<0){
                break;
            }
            if (exsits.contains(sd.site1)||exsits.contains(sd.site2)){
                continue;
            }
            selectedList.add(sd);
            ids.remove(sd.site1.getId());
            exsits.add(sd.site1);
            exsits.add(sd.site2);
        }
        List<SiteSelection> siteSelectionList = new ArrayList<SiteSelection>(selectedList.size());
        for (SiteDistance siteDistance:selectedList){
            List<NetworkDelivery> siteCoverList = new ArrayList<NetworkDelivery>();
            BigDecimal total = new BigDecimal(0);
            BigDecimal totalCX = new BigDecimal(0);
            BigDecimal totalCY = new BigDecimal(0);
            for (NetworkDelivery networkDelivery:secondDeliveryList){
                if(networkDelivery.getpId().equals(siteDistance.site1.getId())||networkDelivery.getpId().equals(siteDistance.site2.getId())){
                    totalCX = totalCX.add(networkDelivery.getCoordinateX().multiply(networkDelivery.getOrderQuantity()));
                    totalCY = totalCY.add(networkDelivery.getCoordinateY().multiply(networkDelivery.getOrderQuantity()));
                    total = total.add(networkDelivery.getOrderQuantity());
                }
            }
            BigDecimal centerCX = totalCX.divide(total, 10, BigDecimal.ROUND_HALF_EVEN);
            BigDecimal centerCY = totalCY.divide(total, 10, BigDecimal.ROUND_HALF_EVEN);
            JSONObject result = Geocoder.getAddressComponent(centerCX, centerCY);
            System.out.println(result.getJSONObject("addressComponent"));
            siteSelectionList.add(new SiteSelection(result.getJSONObject("addressComponent").getString("city"), centerCX, centerCY, siteDistance.site1.getOrderQuantity().add(siteDistance.site2.getOrderQuantity()),0L));
        }
        Double[][] table = new Double[siteSelectionList.size()][secondDeliveryList.size()];
        List<Long> cList = new ArrayList<Long>(siteSelectionList.size());
        List<Long> vList = new ArrayList<Long>(secondDeliveryList.size());
        for (int i=0;i<siteSelectionList.size();i++){
            for (int j=0;j<secondDeliveryList.size();j++){
                table[i][j] = CityUtil.getDistance(
                        siteSelectionList.get(i).getCoordinateX().doubleValue(),
                        siteSelectionList.get(i).getCoordinateY().doubleValue(),
                        secondDeliveryList.get(j).getCoordinateX().doubleValue(),
                        secondDeliveryList.get(j).getCoordinateY().doubleValue());
            }
            cList.add(siteSelectionList.get(i).getOrder().longValue());
        }
        for (int i=0;i<secondDeliveryList.size();i++){
            vList.add(secondDeliveryList.get(i).getOrderQuantity().longValue());
        }
        List<Pos> posList = new ArrayList<Pos>();
        while(isContiue(table)){
            List<Double> rowList = new ArrayList<Double>();
            for (int i=0;i<table.length;i++){
                for (int j=0;j<table[i].length;j++){
                    if (table[i][j]>0){
                        rowList.add(table[i][j]);
                    }
                }
                if (rowList.size()==1){
                    posList.add(new Pos(i,null,rowList.get(0)));
                }else {
                    Collections.sort(rowList);
                    Double pn = rowList.get(1) - rowList.get(0);
                    posList.add(new Pos(i, null, pn));
                }
            }
            for (int i=0;i<vList.size();i++){
                for (int j=0;j<table.length;j++){
                    if (table[j][i]>0){
                        rowList.add(table[j][i]);
                    }
                }
                if (rowList.size()==1){
                    posList.add(new Pos(null,i,rowList.get(0)));
                }else {
                    Collections.sort(rowList);
                    Double pn = rowList.get(1) - rowList.get(0);
                    posList.add(new Pos(null,i, pn));
                }
            }
            Collections.sort(posList, new Comparator<Pos>() {
                @Override
                public int compare(Pos o1, Pos o2) {
                    return o2.pn.compareTo(o1.pn);
                }
            });
            int row = 0;
            int cell = 0;
            double temp=0;
            if (posList.get(0).row==null){
                for (int i=0;i<vList.size();i++){
                    if(table[posList.get(0).cell][i]!=-1&&table[posList.get(0).cell][i]<temp){
                        row=posList.get(0).cell;
                        cell=i;
                        temp=table[posList.get(0).cell][i];
                    }
                }
            }else {
                for (int i=0;i<vList.size();i++){
                    if(table[i][posList.get(0).row]!=-1&&table[i][posList.get(0).row]<temp){
                        row=posList.get(0).row;
                        cell=i;
                        temp=table[i][posList.get(0).row];
                    }
                }
            }
        }








    }
    public boolean isContiue(Double[][] table){
        for (int i=0;i<table.length;i++){
            for (int j=0;j<table[i].length;i++){
                if (table[i][j]>0){
                    return true;
                }
            }
        }
        return false;
    }
    public List<NetworkDelivery> getNetworkDelivey(){
        EntityWrapper<NetworkDelivery> wrapper = new EntityWrapper<NetworkDelivery>();
        wrapper.eq("batch_id", 59);
        wrapper.eq("operator_id",2);
        List<NetworkDelivery> networkDeliveries = networkDeliveryDao.selectList(wrapper);
        return networkDeliveries;
    }
    public BigDecimal getStep1(List<NetworkDelivery> firstDeliveryList){
        BigDecimal bigDecimalSum=new BigDecimal(0);
        for (int i=0;i<firstDeliveryList.size();i++){
            bigDecimalSum.add(firstDeliveryList.get(i).getOrderQuantity());
        }
        return bigDecimalSum.divide(new BigDecimal(firstDeliveryList.size()));
    }
    public  class Pos {
        final Integer row;
        final Integer cell;
        final Double pn;

        public Pos(Integer row, Integer cell, Double pn) {
            this.row = row;
            this.cell = cell;
            this.pn = pn;
        }
    }


}
